/*    
 * THis file is part of the xoperator SPARQL/XMPP agent.
 * For further information see: http://xoperator.sf.net
 * Copyright (C) 2007  Jörg Unbehauen  

 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 */
package net.sf.xoperator.startup;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import net.sf.xoperator.blackboard.NoCloningCloneStrategy;
import net.sf.xoperator.blackboard.NoPlanBlackBoardControl;
import net.sf.xoperator.blackboard.ThreadsafeObjectBlackboard;
import net.sf.xoperator.configuration.SerializingPersonalDataStore;
import net.sf.xoperator.debug.LoggingKS;
import net.sf.xoperator.namespaces.NamespaceKS;
import net.sf.xoperator.store.RDFStoreHTTPAdaptor;
import net.sf.xoperator.store.RdfStoreInfo;
import net.sf.xoperator.ui.UIDelegate;
import net.sf.xoperator.ui.trans.SPARQL2TextTransformer;
import net.sf.xoperator.ui.txt.AddAimlTemplate;
import net.sf.xoperator.ui.txt.AddDatastoreCommand;
import net.sf.xoperator.ui.txt.AddNamespaceCommand;
import net.sf.xoperator.ui.txt.HelpCommand;
import net.sf.xoperator.ui.txt.Interaction;
import net.sf.xoperator.ui.txt.Interactor;
import net.sf.xoperator.ui.txt.ListAimlTemplates;
import net.sf.xoperator.ui.txt.ListDatastoresCommand;
import net.sf.xoperator.ui.txt.ListNamespacesCommand;
import net.sf.xoperator.ui.txt.QueryCommand;
import net.sf.xoperator.ui.txt.RemoveAimlTemplate;
import net.sf.xoperator.ui.txt.RemoveDatastoreCommand;
import net.sf.xoperator.ui.txt.RemoveNamespaceCommand;
import net.sf.xoperator.xmpp.AccountInfo;
import net.sf.xoperator.xmpp.XMPPManager;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.PropertyConfigurator;
import org.openbbs.blackboard.Blackboard;

/**
 * starts the client form the commandline with logininformation provided via
 * parameters
 * 
 * @author joerg
 * 
 */
public class CommandLineMain {
	{
		// PropertyConfigurator.configure();
		// new PropertyConfigurator();
	}

	Options options = new Options();

	private Log log = LogFactory.getLog(CommandLineMain.class);

	public CommandLineMain() {
		options
				.addOption(OptionBuilder
						.withArgName("main_username")
						.hasArg()
						.isRequired(true)
						.withDescription(
								"provide the full login name for your jabber account, e.g. peter@example.com")
						.create("main_username"));
		options.addOption(OptionBuilder.withArgName("main_password").hasArg()
				.isRequired(true).withDescription(
						"The password for the jabber account").create(
						"main_password"));
		options
				.addOption(OptionBuilder
						.withArgName("main_server")
						.hasArg()
						.isRequired(false)
						.withDescription(
								"the server to connect to, if it is not the one specified int the login name")
						.create("main_server"));
		options.addOption(OptionBuilder.withArgName("main_port").hasArg()
				.isRequired(false).withDescription(
						"The port of the server, defaults to 5222").create(
						"main_port"));

		options.addOption(OptionBuilder.withArgName("proxy_username").hasArg()
				.isRequired(false).withDescription(
						"if a proxy user is already knwown, provide it here")
				.create("proxy_username"));
		options
				.addOption(OptionBuilder
						.withArgName("proxy_password")
						.hasArg()
						.isRequired(false)
						.withDescription(
								"if the password for the proxy user is already knwon, provide it here")
						.create("proxy_password"));
		options
				.addOption(OptionBuilder
						.withArgName("proxy_server")
						.hasArg()
						.isRequired(false)
						.withDescription(
								"the server to connect to for the proxy account, if it is not the one specified int the login name")
						.create("proxy_server"));
		options
				.addOption(OptionBuilder
						.withArgName("proxy_port")
						.hasArg()
						.isRequired(false)
						.withDescription(
								"The port of the server to connect to for the roxy account, defaults to 5222")
						.create("proxy_port"));
		options.addOption(OptionBuilder.withArgName("group_agent").hasArg()
				.isRequired(false).withDescription(
						"if set to to true, no proxy account will be used")
				.create("group_agent"));
		options.addOption(OptionBuilder.withArgName("p2penabled").hasArg()
				.isRequired(false).withDescription(
						"if set to to true, p2p communication is activated")
				.create("p2penabled"));

	}

	public void startUp(String[] args) {
		log
				.debug("Starting the application, got the following paramters by the commandline:");
		for (String arg : args) {
			log.debug(arg);
		}
		log.debug("End of the argument list");
		System.out.println("Starting the client");
		CommandLineParser parser = new GnuParser();
		AccountInfo main = new AccountInfo();
		AccountInfo proxy = new AccountInfo();
		try {
			CommandLine cl = parser.parse(options, args);

			main.setUsername(cl.getOptionValue("main_username"));
			main.setPassword(cl.getOptionValue("main_password"));
			main.setServer(cl.getOptionValue("main_server"));
			main.setPort(cl.getOptionValue("main_port") != null ? Integer
					.parseInt(cl.getOptionValue("main_port")) : null);

			main
					.setStandalone(cl.getOptionValue("group_agent") != null ? Boolean
							.parseBoolean(cl.getOptionValue("group_agent"))
							: false);
			main
					.setP2penabled(cl.getOptionValue("p2penabled") != null ? Boolean
							.getBoolean(cl.getOptionValue("p2penabled"))
							: false);
			main.setMainAccount(true);

			if (main.isStandalone()) {
				proxy = null;
			} else {
				proxy.setUsername(cl.getOptionValue("proxy_username"));
				proxy.setPassword(cl.getOptionValue("proxy_password"));
				proxy.setServer(cl.getOptionValue("proxy_server"));
				proxy.setPort(cl.getOptionValue("proxy_port") != null ? Integer
						.parseInt(cl.getOptionValue("proxy_port")) : null);
				proxy.setMainAccount(false);
			}

		} catch (ParseException e) {
			System.out.println(e.getMessage());
			HelpFormatter hform = new HelpFormatter();
			hform.printHelp("Parameters are: ", options);
			System.exit(0);
		}

		createAndRegisterApplication(main, proxy);

	}

	public void createAndRegisterApplication(AccountInfo main, AccountInfo proxy) {
		Blackboard bboard = new ThreadsafeObjectBlackboard(
				new NoCloningCloneStrategy());
		NoPlanBlackBoardControl control = new NoPlanBlackBoardControl(bboard);

		control.registerKnowledgeSource(new RDFStoreHTTPAdaptor());
		control.registerKnowledgeSource(new XMPPManager(control));
		control.registerKnowledgeSource(new SPARQL2TextTransformer());
		control.registerKnowledgeSource(new LoggingKS(control));
		control.registerKnowledgeSource(new NamespaceKS());

		// Constructing the userinterface

		List<Interaction> interactions = new ArrayList<Interaction>();
		interactions.add(new QueryCommand());
		interactions.add(new HelpCommand());
		interactions.add(new ListDatastoresCommand());
		interactions.add(new AddDatastoreCommand());
		interactions.add(new RemoveDatastoreCommand());

		interactions.add(new AddAimlTemplate());
		interactions.add(new ListAimlTemplates());
		interactions.add(new RemoveAimlTemplate());

		interactions.add(new AddNamespaceCommand());
		interactions.add(new RemoveNamespaceCommand());
		interactions.add(new ListNamespacesCommand());

		Interactor interact = new Interactor(interactions, control);
		control.registerKnowledgeSource(new UIDelegate(interact, control));

		// starting the system by intializing the data store, which loads the
		// configuration
		SerializingPersonalDataStore store = new SerializingPersonalDataStore(
				control);
		control.registerKnowledgeSource(store);
		store.initialize(main, proxy);
	}
	


	public static void main(String[] args) {

		CommandLineMain main = new CommandLineMain();

		main.startUp(args);
		Object obj  = new Object();
		try {
			synchronized (obj) {
				obj.wait();
			}
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
//		int exit = 0;
//		try {
//			while (exit!=-1) {
//				//exit = System.in.read();
//				
//			}
//
//		} catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}

	}
}
